package insight.google.game.era.core.hub;

import insight.google.game.era.bo.GameRoom;
import insight.google.game.era.bo.GameUser;
import insight.google.game.era.bo.Task;
import insight.google.game.era.client.proxy.RoomClientProxyImpl;
import insight.google.game.era.core.GameCenterManager;
import insight.google.game.era.core.Util;
import insight.google.game.era.core.cache.AppCacheManager;
import insight.google.game.era.core.cache.GameCacheManager;
import insight.google.game.era.core.cache.PendingEventCacheManager;
import insight.google.game.era.core.cache.UserCacheManager;
import insight.google.game.era.data.GameCenterDataManager;
import insight.google.game.era.data.RoomDataManager;
import insight.google.game.era.data.User;
import insight.google.game.era.data.UserDataManager;
import insight.google.game.era.mgr.FlowManager;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import net.sf.jsr107cache.Cache;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import com.google.appengine.api.datastore.KeyFactory;

public class HubServiceManager {

	private static final Log log = LogFactory.getLog(HubServiceManager.class);
	private static HubServiceManager instance = new HubServiceManager();
	Map<String, UserPendingEvents> pendingUsersMap = new HashMap<String, UserPendingEvents>();
	// private Cache cache;
//	private PendingEventCacheManager userPendingEventCacheManager = new PendingEventCacheManager();

	private HubServiceManager() {
		// cache = AppCacheManager.getInstance().getCache();
	}

	public static HubServiceManager getInstance() {
		return instance;
	}

	public synchronized void updateUser(int gameCenterVersion, int roomVersion) throws Exception {
		// GameUser user = Util.getUserBySession();
		log.debug("update user start ...");
		try{
			this.processGameCenterVersionConflict(gameCenterVersion);
			this.processResult();
			this.processGameRoomVersionConflict(roomVersion);
			
		}catch(Exception e){
			e.printStackTrace();
			//log.info(e.printStackTrace());
		}
		
		this.proceesHangGameUser(roomVersion);
		//this.processGameUserOnTurn();
		
		
	}
	
	private void processResult(){
		User user = Util.getUserBySession();
		GameCacheManager gameCache = new GameCacheManager();
	
		if (user!= null && gameCache.getFromCache(user.getEmail()) != null) {
			List<Map> winners = (List<Map>) gameCache.getFromCache(user.getEmail());
			RoomClientProxyImpl.getInstance().showGameResult(user.getScriptProxy(), "room_instance", winners);
			gameCache.getCache().remove(user.getEmail());
//			user.getScriptProxy().addFunctionCall("componentExecFunctionWithCall","mainframe_instance","userQuitRoom");
			GameCenterManager gameCenterManager = GameCenterManager.getInstance();
			user.getScriptProxy().addFunctionCall("componentExecFunctionWithCall","mainframe_instance","userQuitRoom");
			gameCenterManager.broadCastUsers("");
//			gameCenterManager.updateGameCenter();
		}
	}
	
	private void proceesHangGameUser(int roomVersion){
		User user = Util.getUserBySession();
		
		if (user != null && user.getRoomId() != null) {
			RoomDataManager roomDataManager =new RoomDataManager();
			GameRoom room = roomDataManager.findByName(user.getRoomName());
			GameUser gameUser = Util.getUserByNameAndRoom(room, user);
			if(gameUser != null){
				gameUser.setScriptProxy(user.getScriptProxy());
				if(gameUser.getIsHanged() 
						&& (room.getTaskList() == null || room.getTaskList().isEmpty())){
					room.checkActiveHangeUser(roomVersion, gameUser);
				}
			}
			
		}
		
		
//		try{
//			User user = Util.getUserBySession();
//			
//			if (user != null && user.getRoomId() != null) {
//				RoomDataManager roomDataManager =new RoomDataManager();
//				GameRoom room = roomDataManager.findByName(user.getRoomName());
//				GameUser gameUser = Util.getUserByNameAndRoom(room, user);
//				gameUser.setScriptProxy(user.getScriptProxy());
//				
//				if(gameUser.getIsHanged() 
//						&& (room.getTaskList() == null || room.getTaskList().isEmpty())){
//					room.checkActiveHangeUser(roomVersion, gameUser);
//				}
			}
			
//			if(room.getHangUser() != null 
//					&& (room.getTaskList() == null || room.getTaskList().isEmpty())){
//				GameUser gameUser = Util.getUserByNameAndRoom(room, room.getHangUser());
//				gameUser.setScriptProxy(user.getScriptProxy());
//				gameUser.setActive(true);
//				gameUser.setOnTurn(true);
//				roomDataManager.addToDataStore(room);
//			}
//			else if(room.getTaskList() != null && !room.getTaskList().isEmpty()){
//		        List<Task> tasklist = room.getTaskList();
//		        if(tasklist.size() > 1){
//		        	Task task = tasklist.get(0);
//		            String trgUserName = task.getTargetUserName();
//		            User trgUser = userDataManager.findByName(trgUserName);
//		            GameRoom trgroom = roomDataManager.findByName(trgUser.getRoomName());
//		            GameUser trgGameUser = Util.getUserByNameAndRoom(room, room.getHangUser());
//		            trgGameUser.setScriptProxy(trgUser.getScriptProxy());
//		            trgGameUser.setActive(true);
//		            trgGameUser.setOnTurn(true);
//					roomDataManager.addToDataStore(trgroom);
//		        }
//			}
//
//			roomDataManager.commit();
//		}finally{
//			if(roomDataManager!=null){
//				roomDataManager.close();
//			}
//		}
	
//	private void processGameUserOnTurn(){
//		RoomDataManager roomDataManager = null;
//		try{
//			UserDataManager userDataManager =new UserDataManager(Util.createTranscationHandler(),true);
//
//			User user = Util.getUserBySession(userDataManager.getTransactionHandler(),true);
//			roomDataManager =new RoomDataManager(userDataManager.getTransactionHandler(),true);
//			GameRoom room = roomDataManager.findByName(user.getRoomName());
//
//			GameUser gameUser = Util.getUserByNameAndRoom(room, user);
//			gameUser.setScriptProxy(user.getScriptProxy());
//			
//			if(room.getFlowMgr() == null){
//				return;
//			}
//			
//			if(gameUser != null && gameUser.getIsActive() && gameUser.isOnTurn()){
//				gameUser.setOnTurn(false);
//
//				System.out.println("room.getUserList().get(0).isOnTurn() before save" + room.getUserList().get(0).isOnTurn());
//				System.out.println("gameUser.getName() before save" + gameUser.getName());
//				roomDataManager.addToDataStore(room);
//				roomDataManager.commit();
//				roomDataManager.close();
//				System.out.println("room.getUserList().get(0).isOnTurn() after save" + room.getUserList().get(0).isOnTurn());
//				
//				//get transaction again
//				userDataManager =new UserDataManager(Util.createTranscationHandler());
//				roomDataManager =new RoomDataManager(userDataManager.getTransactionHandler());
//				room = roomDataManager.findByName(user.getRoomName());
//
//				gameUser = Util.getUserByNameAndRoom(room, user);
//				gameUser.setScriptProxy(user.getScriptProxy());
//				
//				System.out.println("room.getUserList().get(0).isOnTurn() get data store" + room.getUserList().get(0).isOnTurn());
//				System.out.println("gameUser.getName() get data store" + gameUser.getName());
//				//on turn execution
//				room.userOnTurn(room, gameUser);
//				roomDataManager.addToDataStore(room);
//				roomDataManager.commit();
//			}
//			if(gameUser.getEventList() != null 
//					&& !gameUser.getEventList().isEmpty()){
//				List<PendingEvents> events = gameUser.getEventList();
//				//set event list to empty and save to data store
//				//in order to execution twice.
//				gameUser.setEventList(new ArrayList<PendingEvents>());
//				
//				roomDataManager.addToDataStore(room);
//				roomDataManager.commit();
//				
//				//get transaction again
//				userDataManager =new UserDataManager(Util.createTranscationHandler());
//				roomDataManager =new RoomDataManager(userDataManager.getTransactionHandler());
//				room = roomDataManager.findByName(user.getRoomName());
//
//				gameUser = Util.getUserByNameAndRoom(room, user);
//				gameUser.setScriptProxy(user.getScriptProxy());
//				
//				//pending event execution
//				gameUser.processPendingEvents(events);
//				roomDataManager.addToDataStore(room);
//				roomDataManager.commit();
//			}
//			
//		}finally{
//			if(roomDataManager!=null){
//				roomDataManager.close();
//			}
//		}
////		else if(user != null){
//////			Util.getUserCurrentRoom(user);
////			
////			//get game room by user
////			GameRoom currentRoom = Util.getUserCurrentRoom(user);
////			GameRoom userCurRoom = user.getCurrentRoom();
////			//get user list's user from the game room
////			GameUser currentUser = currentRoom.getCurrentUserByName();
////			if(currentUser != null){
////				user.processPendingEvents();
////			}
////		}
//
//	}

	private void processGameCenterVersionConflict(int version) {
		log.debug("processGameCenterVersionConflict update user start ...");
		GameCenterDataManager gameCenterdataManager = new GameCenterDataManager();
		GameCenterManager gameCenter = GameCenterManager.getInstance();
		gameCenter.processVersionConflict(version);
		log.debug("processGameCenterVersionConflict update user end ...");
		
	}

	private void processGameRoomVersionConflict(int version) {
//		UserDataManager userDataManager =new UserDataManager();
		User user = Util.getUserBySession();
	
		
		if (user != null && user.getRoomId() != null) {
			
			RoomDataManager roomDataManager =new RoomDataManager();
			GameRoom room = roomDataManager.findByName(user.getRoomName());
			room.processVersionConflict(version, user);
		}
		

	}

	public void addToList(UserPendingEvents userPendingEvent) {
//		if (!pendingUsersMap.containsKey(userPendingEvent.getUserName())) {
//			pendingUsersMap.put(userPendingEvent.getUserName(),
//					userPendingEvent);
//		}
	}

	public UserPendingEvents getUserPendingEvents(GameUser user) {
		return pendingUsersMap.containsKey(user.getName()) ? pendingUsersMap
				.get(user.getName()) : null;
	}

	public void addPendingEvent(GameUser user, PendingEvents pendingEvent) {
		pendingEvent.setPendingUser(user);
		user.addPendingEvent(pendingEvent);

//		UserPendingEvents userPendingEvents = null;
//		log.debug(" addPendingEvent --  pendingUsersMap  : " + pendingUsersMap);
//		log.debug(" addPendingEvent --  user  : " + user);
//		if (pendingUsersMap.containsKey(user.getName())) {
//			userPendingEvents = pendingUsersMap.get(user.getName());
//		} else {
//			userPendingEvents = new UserPendingEvents();
//			pendingUsersMap.put(user.getName(), userPendingEvents);
//		}
////		userPendingEvents.setUserName(user.getName());
////		userPendingEvents.getEventList().add(pendingEvent);
////		pendingUsersMap.put(userPendingEvents.getUserName(), userPendingEvents);
////		userPendingEventCacheManager.updateToCache(pendingUsersMap);
//		// cache.put(AppCacheManager.HUB_EVENT_MSG , pendingUsersMap);
	}

	public void addPendingEvent(GameUser user, String jsComponentId,
			Object data, String eventId) {
		log.debug(" addPendingEvent --  EVENT ID  : " + eventId);
		log.debug(" addPendingEvent --  DATA  : " + data);
		PendingEvents pendingEvent = new PendingEvents();
		pendingEvent.setPendingUser(user);
		pendingEvent.setData(data);
		pendingEvent.setFunctionName(eventId.toString());
		pendingEvent.setJsComponentId(jsComponentId);
		this.addPendingEvent(user, pendingEvent);
	}

	private boolean processPendingEvents(GameUser user) {
		//user.processPendingEvents();

//		log.debug("BEFORE USER ### " + user.getName() + "  pendingList  ###  "
//				+ userPendingEvent.getEventList().size());
//		userPendingEvent = userPendingEventCacheManager
//				.getFromCacheByValue(userPendingEvent);
//		if (userPendingEvent != null) {
//			log.debug("AFTER USER ### " + user.getName()
//					+ "  pendingList  ###  "
//					+ userPendingEvent.getEventList().size());
//			synchronized (userPendingEvent) {
//				userPendingEvent.processPendingEvents(user);
//			}
//		}
//
//		log.debug("BEFORE USER ### " + user.getName() + "  pendingList  ###  "
//				+ userPendingEvent.getEventList().size());
//		userPendingEvent = userPendingEventCacheManager
//				.getFromCacheByValue(userPendingEvent);
//		if (userPendingEvent != null) {
//			log.debug("AFTER USER ### " + user.getName()
//					+ "  pendingList  ###  "
//					+ userPendingEvent.getEventList().size());
//			synchronized (userPendingEvent) {
//				userPendingEvent.processPendingEvents(user);
//			}
//		}

		return true;
	}
	
}
